#include "oled.h"
#include "fonts.h"


/*
*   接线：                                             
*   GND ---> GND                                       
*   VCC ---> 3.3V                                      
*   DO  ---> SPI_SCK                                   
*   D1  ---> SPI_MOSI                                  
*   RES ---> OLED_RES                                  
*   DC  ---> OLED_DC                                   
*   CS  ---> OLED_CS 
*/
extern SPI_HandleTypeDef hspi2;

u8 OLED_GRAM[128][8];	
void OLED_Write_Byte( u8 data , u8 cmd )
{
                                           // 这里直接使用三目运算符，不使用if/else写法，看起来简洁些
    cmd ? OLED_DC_L : OLED_DC_H ; 				// 写命令DC输出低，写数据DC输出高
                                          // 硬件SPI数据传输
    HAL_SPI_Transmit(&hspi2,&data,sizeof(data),1000); // SPI写数据或者命令
    OLED_DC_H;														// 控制脚拉高，置成写数据状态
}

/********************
** OLED清屏操作
*********************/
void OLED_Clear(void)
{
    u8 i,n;
    for(i=0; i<8; i++)
    {
        OLED_Write_Byte (0xb0+i,OLED_CMD);    //设置页地址（0~7）
        OLED_Write_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
        OLED_Write_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址
        for(n=0; n<128; n++)OLED_Write_Byte(0,OLED_DATA); // 每一列都置零
    }
}



/*******************
** OLED初始化
********************/
void OLED_Init(void)
{
    // 制造一个先低后高的电平变换，达到复位的效果
    OLED_RST_L;
    HAL_Delay(500);
    OLED_RST_H;

    OLED_Write_Byte(0xAE,OLED_CMD);//--turn off oled panel
    OLED_Write_Byte(0x02,OLED_CMD);//---set low column address
    OLED_Write_Byte(0x10,OLED_CMD);//---set high column address
    OLED_Write_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
    OLED_Write_Byte(0x81,OLED_CMD);//--set contrast control register
    OLED_Write_Byte(0xff,OLED_CMD);// Set SEG Output Current Brightness
    OLED_Write_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
    OLED_Write_Byte(0xC0,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
    OLED_Write_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
    OLED_Write_Byte(0x3f,OLED_CMD);//--1/64 duty
    OLED_Write_Byte(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
    OLED_Write_Byte(0x00,OLED_CMD);//-not offset
    OLED_Write_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
    OLED_Write_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
    OLED_Write_Byte(0xD9,OLED_CMD);//--set pre-charge period
    OLED_Write_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
    OLED_Write_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
    OLED_Write_Byte(0x12,OLED_CMD);
    OLED_Write_Byte(0xDB,OLED_CMD);//--set vcomh
    OLED_Write_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
    OLED_Write_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
    OLED_Write_Byte(0x02,OLED_CMD);//
    OLED_Write_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
    OLED_Write_Byte(0x14,OLED_CMD);//--set(0x10) disable
    OLED_Write_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
    OLED_Write_Byte(0xA6,OLED_CMD);// 开启正常显示 (0xA6 = 正常 / 0xA7 = 反显)
    OLED_Write_Byte(0xAF,OLED_CMD);//--turn on oled panel

    OLED_Clear(); // 清屏
}

void OLED_On(void)
{
    OLED_Write_Byte(0X8D,OLED_CMD);  //SET DCDC命令
    OLED_Write_Byte(0X14,OLED_CMD);  //DCDC ON
    OLED_Write_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}

/******************
**  关闭OLED显示
*******************/
void OLED_Off(void)
{
    OLED_Write_Byte(0X8D,OLED_CMD);  //SET DCDC命令
    OLED_Write_Byte(0X10,OLED_CMD);  //DCDC OFF
    OLED_Write_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}


//画点 
//x:0~127
//y:0~63
//t:1 填充 0,清空				   
void OLED_DrawPoint(u8 x,u8 y,u8 t)
{
	u8 pos,bx,temp=0;
	if(x>127||y>63)return;//超出范围了.
	pos=7-y/8;
	bx=y%8;
	temp=1<<(7-bx);
	if(t)OLED_GRAM[x][pos]|=temp;
	else OLED_GRAM[x][pos]&=~temp;	    
}

//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示				 
//size:选择字体 16/12 
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)
{      			    
	u8 temp,t,t1;
	u8 y0=y;
	chr=chr-' ';//得到偏移后的值				   
    for(t=0;t<size;t++)
    {   
		if(size==12)temp=oled_asc2_1206[chr][t];  //调用1206字体
		else temp=oled_asc2_1608[chr][t];		 //调用1608字体 	                          
        for(t1=0;t1<8;t1++)
		{
			if(temp&0x80)OLED_DrawPoint(x,y,mode);
			else OLED_DrawPoint(x,y,!mode);
			temp<<=1;
			y++;
			if((y-y0)==size)
			{
				y=y0;
				x++;
				break;
			}
		}  	 
    }          
}
//m^n函数
uint32_t oled_pow(u8 m,u8 n)
{
	uint32_t result=1;	 
	while(n--)result*=m;    
	return result;
}				  
//显示2个数字
//x,y :起点坐标	 
//len :数字的位数
//size:字体大小
//mode:模式	0,填充模式;1,叠加模式
//num:数值(0~4294967295);	 		  
void OLED_ShowNumber(u8 x,u8 y,uint32_t num,u8 len,u8 size)
{         	
	u8 t,temp;
	u8 enshow=0;						   
	for(t=0;t<len;t++)
	{
		temp=(num/oled_pow(10,len-t-1))%10;
		if(enshow==0&&t<(len-1))
		{
			if(temp==0)
			{
				OLED_ShowChar(x+(size/2)*t,y,' ',size,1);
				continue;
			}else enshow=1; 
		 	 
		}
	 	OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1); 
	}
} 
//显示字符串
//x,y:起点坐标  
//*p:字符串起始地址
//用16字体
void OLED_ShowString(u8 x,u8 y,const u8 *p)
{
#define MAX_CHAR_POSX 122
#define MAX_CHAR_POSY 58          
    while(*p!='\0')
    {       
        if(x>MAX_CHAR_POSX){x=0;y+=16;}
        if(y>MAX_CHAR_POSY){y=x=0;OLED_Clear();}
        OLED_ShowChar(x,y,*p,12,1);	 
        x+=8;
        p++;
    }  
}	

void OLED_Refresh_Gram(void)
{
	u8 i,n;		    
	for(i=0;i<8;i++)  
	{  
		OLED_Write_Byte(0xb0+i,OLED_CMD);    //设置页地址（0~7）
		OLED_Write_Byte(0x00,OLED_CMD);      //设置显示位置—列低地址
		OLED_Write_Byte(0x10,OLED_CMD);      //设置显示位置—列高地址   
		for(n=0;n<128;n++)OLED_Write_Byte(OLED_GRAM[n][i],OLED_DATA); 
	}   
}

//屏幕旋转180度
void OLED_DisplayTurn(uint8_t i)
{
	if(i==0)
		{
			OLED_Write_Byte(0xC8,OLED_CMD);//正常显示
			OLED_Write_Byte(0xA1,OLED_CMD);
		}
	if(i==1)
		{
			OLED_Write_Byte(0xC0,OLED_CMD);//反转显示
			OLED_Write_Byte(0xA0,OLED_CMD);
		}
}
